package flib;

import java.util.Arrays;
import java.util.Vector;

import processing.core.PGraphics;
import simpleGeom.Rect2D;

public class Sub {
	FlibLevel level;
	boolean[] occupied;
	boolean[] blocked;

	public Sub(FlibLevel level) {
		this.level = level;
		occupied = new boolean[level.rooms.size()];
		blocked = new boolean[level.rooms.size()];
	}

	public Vector<Room> getRooms() {
		Vector<Room> rooms = new Vector<Room>();
		for (int i = 0; i < level.rooms.size(); i++) {
			Room r = level.rooms.get(i);
			if (occupied[r.id]) {
				rooms.add(r);
			}
		}
		return rooms;
	}

	public Vector<Vector<Room>> collectAppartments() {
		// entrance and go...
		boolean[] checked = new boolean[level.rooms.size()];
		for (int i = 0; i < level.rooms.size(); i++) {
			Room room = level.rooms.get(i);
			checked[i] = false;
			
		}
		
		
		// entrance and go...
		Vector<Vector<Room>> appartments = new Vector<Vector<Room>>();
		for (int i = 0; i < level.rooms.size(); i++) {
			Room room = level.rooms.get(i);
			boolean isStart = false;

			if (occupied[room.id] && !room.ispublic && !checked[room.id]) {

				FlibHEdge hEdge = room.getHEdge();
				
				do {
					FlibWall wall = ((FlibHEData) hEdge.getData()).wall;
					if (wall.type.permeable
							&& wall.type.label.equals("door-entrance")) {
						
						isStart = true;
						checked[room.id]=true;
						
					}
					hEdge = hEdge.getNext();
				} while (hEdge != room.getHEdge());

			}

			if (isStart) {

				Vector<Room> occupiedApp = new Vector<Room>();
				Vector<Room> app = collectPrivateRooms(room);
				for (int j = 0; j < app.size(); j++) {
					Room r = app.get(j);
					if (occupied[r.id]) {
						checked[r.id] = true;
						occupiedApp.add(r);
					}
				}
				appartments.add(occupiedApp);
			}
		}
		return appartments;
	}

	public Vector<Room> collectPrivateRooms(Room room) {
		boolean[] checked = new boolean[level.rooms.size()];
		checked[room.id] = true;
		Vector<Room> appartment = new Vector<Room>();
		Vector<Room> candidates = new Vector<Room>();
		candidates.add(room);
		appartment.add(room);
		while (candidates.size() > 0) {
			Vector<Room> nextCandidates = new Vector<Room>();
			for (int i = 0; i < candidates.size(); i++) {
				Room cRoom = candidates.get(i);
				FlibHEdge hEdge = room.getHEdge();
				do {
					hEdge = hEdge.getNext();
					FlibWall wall = ((FlibHEData) hEdge.getData()).wall;
					Room nb = (Room) hEdge.getSym().getFace();
					if (nb != null && wall.type.permeable && !nb.ispublic
							&& !checked[nb.id]) {
						nextCandidates.add(nb);
						appartment.add(nb);
						checked[nb.id] = true;
						// room.checked=true;
					}
				} while (hEdge != room.getHEdge());
			}
			candidates = nextCandidates;
		}
		return appartment;
	}

	public boolean checkAppartments(Vector<Room> rooms) {
		boolean hasBath=false;
		boolean hasSize=false;
		for (int i=0;i<rooms.size();i++){
			Room room=rooms.get(i);
			if (room.type!=null&&room.type.label.contains("bath")){
				hasBath=true;
			}
			else if (Math.abs(room.getArea2D())>16){
				hasSize=true;
			}
		}
		if (!hasSize)return false;
		if (!hasBath)return false;
		return true;
		// minimum one bathroom, and one room>15 qm
	}

	public Vector<FlibWall> getWalls() {
		Vector<FlibWall> walls = new Vector<FlibWall>();
		for (int i = 0; i < level.walls.size(); i++) {
			FlibWall w = level.walls.get(i);
			Room r1 = w.getR1();
			Room r2 = w.getR2();

			if (r1 != null && occupied[r1.id] || r2 != null && occupied[r2.id]) {
				walls.add(w);
			}
		}
		return walls;
	}

	public Rect2D getBounds() {
		Rect2D b2d = null;
		for (int i = 0; i < level.rooms.size(); i++) {
			Room r = level.rooms.get(i);
			if (occupied[r.id]) {
				if (b2d == null) {
					b2d = r.getBounds2D();
				} else {
					b2d.addRect2D(r.getBounds2D());
				}
			}
		}
		return b2d;
	}

	public Vector<Room> getRoomsToAdd() {
		Vector<Room> roomsToAdd = new Vector<Room>();
		for (int i = 0; i < level.rooms.size(); i++) {
			Room r = level.rooms.get(i);
			/*
			 * println("r: "+r.id); println("occ: "+occupied[r.id]);
			 * println("blocked: "+blocked[r.id]);
			 */
			if (!blocked[r.id] && !occupied[r.id]) {
				FlibHEdge hEdge = r.getHEdge();
				do {
					FlibWall wall = ((FlibHEData) hEdge.getData()).wall;
					if (wall.type.permeable
							&& !wall.type.label.equals("door-entrance")) {
						Room nb = (Room) hEdge.getSym().getFace();
						if (nb != null) {
							if (occupied[nb.id]) {
								roomsToAdd.add(r);
								hEdge = r.getHEdge().getPrev();
							}
						}
					}
					hEdge = hEdge.getNext();

				} while (hEdge != r.getHEdge());
			}
		}
		return roomsToAdd;
	}

	public Vector<Room> getRoomsToAddDoor() {
		Vector<Room> roomsToAdd = new Vector<Room>();
		for (int i = 0; i < level.rooms.size(); i++) {
			Room r = level.rooms.get(i);
			/*
			 * println("r: "+r.id); println("occ: "+occupied[r.id]);
			 * println("blocked: "+blocked[r.id]);
			 */
			if (!blocked[r.id] && !occupied[r.id]) {
				FlibHEdge hEdge = r.getHEdge();
				do {
					FlibWall wall = ((FlibHEData) hEdge.getData()).wall;
					if (wall.type.permeable) {
						Room nb = (Room) hEdge.getSym().getFace();
						if (nb != null) {
							if (occupied[nb.id]) {
								roomsToAdd.add(r);
								hEdge = r.getHEdge().getPrev();
							}
						}
					}
					hEdge = hEdge.getNext();

				} while (hEdge != r.getHEdge());
			}
		}
		return roomsToAdd;
	}

	public Sub copy() {
		Sub sub = new Sub(level);
		sub.blocked = Arrays.copyOf(blocked, blocked.length);
		sub.occupied = Arrays.copyOf(occupied, occupied.length);
		return sub;
	}

	public void display(PGraphics g) {

		for (int i = 0; i < level.rooms.size(); i++) {
			Room r = level.rooms.get(i);
			if (occupied[r.id]) {
				r.display(g);
			}
		}
	}
}
